import router from '@/router'
import type {
  AxiosError,
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig
} from 'axios'
import axios from 'axios'
import { ElLoading, ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import { nextTick } from 'vue'
import { getToken, removeToken } from './auth'

NProgress.configure({ showSpinner: false })

// 扩展 AxiosRequestConfig 接口
interface CustomRequestConfig extends AxiosRequestConfig {
  loading?: boolean
  loadingText?: string
  successMessage?: string
  errorMessage?: string
}

// 响应数据结构
interface ResponseData<T = any> {
  code: number
  message: string
  data: T
  timestamp?: number
}

let loadingInstance: any = null

class Request {
  instance: AxiosInstance

  constructor(config?: AxiosRequestConfig) {
    this.instance = axios.create({
      baseURL: import.meta.env.VITE_API_BASE_URL,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json;charset=utf-8'
      },
      ...config
    })

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        NProgress.start()

        // 添加 token
        const token = getToken()
        if (token && config.headers) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 显示 loading
        const customConfig = config as CustomRequestConfig
        if (customConfig.loading) {
          loadingInstance = ElLoading.service({
            lock: true,
            text: customConfig.loadingText || '加载中...',
            background: 'rgba(0, 0, 0, 0.7)'
          })
        }

        return config
      },
      (error: AxiosError) => {
        NProgress.done()
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ResponseData>) => {
        NProgress.done()

        nextTick(() => {
          if (loadingInstance) {
            loadingInstance.close()
            loadingInstance = null
          }
        })

        const { code, message, data } = response.data
        const customConfig = response.config as CustomRequestConfig

        // 成功响应（code 为 0 或 200）
        if (code === 0 || code === 200) {
          // 显示成功消息
          if (customConfig.successMessage) {
            ElMessage.success(customConfig.successMessage)
          }
          return data
        }

        // 未登录或 token 失效
        if (code === 401) {
          ElMessage.error('登录已过期，请重新登录')
          removeToken()
          router.push('/login')
          return Promise.reject(new Error('Unauthorized'))
        }

        // 无权限
        if (code === 403) {
          ElMessage.error(message || '暂无权限访问')
          return Promise.reject(new Error('Forbidden'))
        }

        // 其他错误
        ElMessage.error(message || '请求失败')
        return Promise.reject(new Error(message || 'Request failed'))
      },
      (error: AxiosError<ResponseData>) => {
        NProgress.done()

        nextTick(() => {
          if (loadingInstance) {
            loadingInstance.close()
            loadingInstance = null
          }

          const customConfig = error.config as CustomRequestConfig
          if (customConfig?.errorMessage) {
            ElMessage.error(customConfig.errorMessage)
          }
        })

        // 处理 HTTP 状态码
        if (error.response) {
          handleHttpError(error.response.status, error.response.data?.message)
        } else if (error.message) {
          if (error.message.includes('timeout')) {
            ElMessage.error('请求超时，请稍后重试')
          } else if (error.message.includes('Network Error')) {
            ElMessage.error('网络连接失败，请检查网络')
          } else {
            ElMessage.error('请求失败：' + error.message)
          }
        }

        return Promise.reject(error)
      }
    )
  }

  // 常用请求方法封装
  get<T = any>(url: string, params?: any, config?: CustomRequestConfig): Promise<T> {
    return this.instance.get(url, { params, ...config })
  }

  post<T = any>(url: string, data?: any, config?: CustomRequestConfig): Promise<T> {
    return this.instance.post(url, data, config)
  }

  put<T = any>(url: string, data?: any, config?: CustomRequestConfig): Promise<T> {
    return this.instance.put(url, data, config)
  }

  delete<T = any>(url: string, params?: any, config?: CustomRequestConfig): Promise<T> {
    return this.instance.delete(url, { params, ...config })
  }

  // 上传文件
  upload<T = any>(url: string, formData: FormData, config?: CustomRequestConfig): Promise<T> {
    return this.instance.post(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      ...config
    })
  }
}

// 处理 HTTP 错误状态码
function handleHttpError(status: number, message?: string): void {
  switch (status) {
    case 400:
      ElMessage.error(message || '请求参数错误')
      break
    case 401:
      ElMessage.error('登录已过期，请重新登录')
      removeToken()
      router.push('/login')
      break
    case 403:
      ElMessage.error(message || '暂无权限访问')
      break
    case 404:
      ElMessage.error(message || '请求的资源不存在')
      break
    case 405:
      ElMessage.error('请求方法不允许')
      break
    case 408:
      ElMessage.error('请求超时')
      break
    case 500:
      ElMessage.error(message || '服务器内部错误')
      break
    case 502:
      ElMessage.error('网关错误')
      break
    case 503:
      ElMessage.error('服务不可用')
      break
    case 504:
      ElMessage.error('网关超时')
      break
    default:
      ElMessage.error(message || `请求失败(${status})`)
  }
}

export default new Request()
export { Request }
export type { CustomRequestConfig, ResponseData }

